#pragma once

#include "json_reflection_utility.h"
#include "WebLogger.h"

#define WEB_MODULE   MAKE_LOG_MODULE("Web API")

template <typename T>
struct GenaralOutput :JsonReflectionBase
{
	int code;
	std::string description;
	T data;

	GenaralOutput() :code(-1) { description = "--"; }

	GenaralOutput(int errCode, const std::string& errDescription = "未知错误") :code(errCode), description(errDescription)
	{
	}

	REFLECT_WEBJSON_OUTPUT_ARGS_NUM(code, description, data)
	REFLECT_WEBJSON_INPUT_ARGS_NUM(code, description, data)
};

//固定的TcpJson头
struct DevTcpJsonHeader :JsonReflectionBase
{
	std::string target;
	int request_type; //1.代表请求  2代表响应

	REFLECT_WEBJSON_INPUT_ARGS_NUM(target, request_type)
	REFLECT_WEBJSON_OUTPUT_ARGS_NUM(target, request_type)
};

template <typename T>
struct GenaralDevTcpJsonOutputContent :JsonReflectionBase
{
	int code;
	std::string description;
	T data;

	GenaralDevTcpJsonOutputContent() :code(-1) { description = "--"; }

	GenaralDevTcpJsonOutputContent(int errCode, const std::string& errDescription = "未知错误") :code(errCode), description(errDescription)
	{
	}

	REFLECT_WEBJSON_OUTPUT_ARGS_NUM(code, description, data)
	REFLECT_WEBJSON_INPUT_ARGS_NUM(code, description, data)
};

template <>
struct GenaralDevTcpJsonOutputContent<void> :JsonReflectionBase
{
	int code;
	std::string description;

	GenaralDevTcpJsonOutputContent() :code(-1) { description = "--"; }

	GenaralDevTcpJsonOutputContent(int errCode, const std::string& errDescription = "未知错误") :code(errCode), description(errDescription)
	{
	}

	REFLECT_WEBJSON_OUTPUT_ARGS_NUM(code, description)
	REFLECT_WEBJSON_INPUT_ARGS_NUM(code, description)
};

template <typename T>
struct GenaralDevTcpJsonOutput :JsonReflectionBase
{
	DevTcpJsonHeader head;
	GenaralDevTcpJsonOutputContent<T> request_content;

	REFLECT_WEBJSON_OUTPUT_ARGS_NUM(head, request_content)
	REFLECT_WEBJSON_INPUT_ARGS_NUM(head, request_content)
};

template <typename T>
struct GenaralDevTcpJsonOutputIns :JsonReflectionBase
{
	DevTcpJsonHeader head;
	T request_content;

	REFLECT_WEBJSON_OUTPUT_ARGS_NUM(head, request_content)
		REFLECT_WEBJSON_INPUT_ARGS_NUM(head, request_content)
};

template <>
struct GenaralOutput<void>:JsonReflectionBase
{
	int code;
	std::string description;

	GenaralOutput(int errCode, const std::string& errDescription = "未知错误") :code(errCode), description(errDescription)
	{
	}

	REFLECT_WEBJSON_OUTPUT_ARGS_NUM(code, description)
	REFLECT_WEBJSON_INPUT_ARGS_NUM(code, description)
};

struct CommonOutput :JsonReflectionBase //共用输出
{

};


template<typename T>
struct GeneralPageInfo
{
	typedef T filter_type;

	int num;                                            // 个数
	int page;                                           // 页数
	int total;                                          // 总数
	boost::optional<T> filter;

	GeneralPageInfo()
	{
		num = 0;
		page = 0;
		total = 0;
	}
};

template<>
struct GeneralPageInfo<void>
{
	int num;                                            // 个数
	int page;                                           // 页数
	int total;                                          // 总数

	GeneralPageInfo()
	{
		num = 0;
		page = 0;
		total = 0;
	}
};



//根据total, num 调整page
template<typename T>
void correctPageInfo(GeneralPageInfo<T>& pageInfo)
{
	if (pageInfo.page < 1)
	{
		pageInfo.page = 1;
	}

	if (pageInfo.page == 1)
	{
		return;
	}

	int need_total = (pageInfo.page-1) * pageInfo.num + 1;
	if (pageInfo.total >= need_total)
	{
		return;
	}

	pageInfo.page = pageInfo.total / pageInfo.num;
	if (pageInfo.total % pageInfo.num != 0)
	{
		++pageInfo.page;
	}

	if (pageInfo.page < 1)
	{
		pageInfo.page = 1;
	}
}

//处理请求
template<typename _In, typename _Out>
static int GenaralOperator(cJSON* pJson, std::string& strJsonBuffer, _In& input, _Out& output, std::function<int(_In&, _Out&, std::string&)> func)
{
	std::string strDesc;
	//将最终调用结果的描述写入日志对象
	std::shared_ptr<void> raii_call_desc((void*)(1), [&strDesc](void*) {
		WebLoggerThreadObject::Get().setDescribe(strDesc);
	});

    std::shared_ptr<cJSON*> raii_output_str(new cJSON*, [&strJsonBuffer](cJSON** ppOutPutJson) {
        if (ppOutPutJson == nullptr)
        {
            return;
        }
		
		if(*ppOutPutJson != nullptr)
		{
			strJsonBuffer = JsonHandler::JsonToString(*ppOutPutJson);
			cJSON_Delete(*ppOutPutJson);
		}

        delete ppOutPutJson;
    });

    //输入
    if (!input.parseWebJsonInput(pJson))
    {
		strDesc = "参数错误";
        GenaralOutput<void> output(1, strDesc);
        *raii_output_str = output.genarateWebJsonOutput();
        TRACE_LOG_A(WEB_MODULE, TRACE_LOG_LEVEL_ERROR, "Json对象解析失败");
        return -1;
    }

    int nReturnCode = 0;

    try
    {
        nReturnCode = func(input, output, strDesc);
		if (nReturnCode == 0 && strDesc.empty())
		{
			strDesc = "成功";
		}

    }
    catch (const std::exception & e)
    {
        TRACE_LOG_A(WEB_MODULE, TRACE_LOG_LEVEL_ERROR, "出现未处理异常 : %s, ", e.what() );
        assert( 1 != 1);
		strDesc = std::string("捕获异常: ") + e.what();
		GenaralOutput<void> output(-111110000, strDesc);
        *raii_output_str = output.genarateWebJsonOutput();
        return -1;
    }

    //输出
    if (nReturnCode == 0)
    {
        GenaralOutput<_Out> genaral_output(nReturnCode, strDesc);
        genaral_output.data = std::move(output);
        *raii_output_str = genaral_output.genarateWebJsonOutput();
    }
    else
    {
        GenaralOutput<void> genaral_output(nReturnCode, strDesc);
        *raii_output_str = genaral_output.genarateWebJsonOutput();
    }

    return 0;
}

